﻿/*
SINACOR - BMF&Bovespa
Arquivo: MonitorAlocacao.cs
Criado em: 30-mar-2010 15:39:46
Arquiteto Responsável: RAMelo.7Comm
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sinacor.Infra.Service.Common;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Infra.Service.Validation;
using Sinacor.Infra.Service.Validation.BusinessRules;
using Sinacor.Servico.Bovespa.Movimento.BusinessEntity;
using Sinacor.Servico.Bovespa.Movimento.ResourceAccess;
using Sinacor.Infra.Service.Security.Authorization;


namespace Sinacor.Servico.Bovespa.Alocacao.BusinessLogic
{
    /// <summary>
    /// Classe de regras de negócio para o monitor de alocação
    /// </summary>
    public class MonitorAlocacao : BaseBusinessLogic
    {
        #region Métodos
        /// <summary>
        /// Analisa a situação da mensagem e a situação na fila para atribuir o estado da
        /// mensagem
        /// </summary>
        /// <param name="entity"></param>
        private BusinessEntity.Enum.EstadoMensagemAlocacao? AtualizarEstadoMensagemAlocacao(BusinessEntity.MensagemAlocacao entity)
        {
            BusinessEntity.Enum.EstadoMensagemAlocacao? estado = null;

            if (entity.EstadoMensagem == "N" || entity.EstadoMensagem == "B")
            {
                estado = BusinessEntity.Enum.EstadoMensagemAlocacao.Gerada;
            }
            else
            {
                if (entity.EstadoMensagem == "S" && entity.EstadoFila == "N")
                {
                    estado = BusinessEntity.Enum.EstadoMensagemAlocacao.Gerada;
                }
                else
                {
                    if (entity.EstadoMensagem == "S" && entity.EstadoFila == "E")
                    {
                        estado = BusinessEntity.Enum.EstadoMensagemAlocacao.FilaEnvio;
                    }
                    else
                    {
                        if (entity.EstadoMensagem == "S" && entity.EstadoFila == "X")
                        {
                            estado = BusinessEntity.Enum.EstadoMensagemAlocacao.Invalidada;
                        }
                        else
                        {
                            if (entity.EstadoMensagem == "S" && entity.EstadoFila == "R")
                            {
                                estado = BusinessEntity.Enum.EstadoMensagemAlocacao.ProcessandoRetorno;
                            }
                            else
                            {
                                if (entity.EstadoMensagem == "A")
                                {
                                    estado = BusinessEntity.Enum.EstadoMensagemAlocacao.Aceita;
                                }
                                else
                                {
                                    if (entity.EstadoMensagem == "E")
                                    {
                                        estado = BusinessEntity.Enum.EstadoMensagemAlocacao.Falha;
                                    }
                                    else
                                    {
                                        if (entity.EstadoMensagem == "P")
                                        {
                                            estado = BusinessEntity.Enum.EstadoMensagemAlocacao.FalhaTratada;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return estado;
        }

        /// <summary>
        /// Realiza a consulta de alocações realizadas
        /// </summary>
        /// <param name="parameter"></param>
        public List<BusinessEntity.MensagemAlocacaoRealizada> ConsultarAlocacoesRealizadas(BusinessEntity.Parameter.FiltroAlocacao parameter)
        {
            List<BusinessEntity.MensagemAlocacaoRealizada> retorno;

            if (parameter != null)
            {
                this.ValidarPermissaoExecucao();
                if (parameter.DataPregao != DateTime.MinValue)
                {
                    if (parameter.NumeroMensagem != 0)
                    {
                        ResourceAccess.MonitorAlocacao raMonitorAlocacao = new Sinacor.Servico.Bovespa.Alocacao.ResourceAccess.MonitorAlocacao();
                        retorno = raMonitorAlocacao.ConsultarAlocacoesRealizadas(parameter);
                    }
                    else
                    {
                        throw new BusinessException(109632);
                    }
                }
                else
                {
                    throw new BusinessException(109630);
                }
            }
            else
            {
                throw new BusinessException(109623);
            }

            return retorno;

        }

        /// <summary>
        /// Consulta os erros de alocação
        /// </summary>
        /// <param name="parameter"></param>
        public List<BusinessEntity.ErroAlocacao> ConsultarErrosAlocacao(BusinessEntity.Parameter.FiltroAlocacao parameter)
        {
            List<BusinessEntity.ErroAlocacao> retorno;

            if (parameter != null)
            {
                this.ValidarPermissaoExecucao();
                if (parameter.DataPregao != DateTime.MinValue)
                {
                    if (parameter.NumeroMensagem != 0)
                    {
                        ResourceAccess.MonitorAlocacao raMonitorAlocaco = new Sinacor.Servico.Bovespa.Alocacao.ResourceAccess.MonitorAlocacao();
                        retorno = raMonitorAlocaco.ConsultarErrosAlocacao(parameter);
                    }
                    else
                    {
                        throw new BusinessException(109631);
                    }
                }
                else
                {
                    throw new BusinessException(109629);
                }
            }
            else
            {
                throw new BusinessException(109626);
            }

            return retorno;
        }

        /// <summary>
        /// Realiza a consulta de mensagens de alocação conforme filtros informados.
        /// </summary>
        /// <param name="parameter"></param>
        public List<BusinessEntity.MensagemAlocacao> ConsultarMensagensAlocacao(BusinessEntity.Parameter.FiltroMonitorAlocacao parameter)
        {
            List<BusinessEntity.MensagemAlocacao> retorno;
            if (parameter != null)
            {
                this.ValidarPermissaoExecucao();
                SinacorValidation validation = new SinacorValidation();
                validation.AddValidation<BusinessEntity.Parameter.FiltroMonitorAlocacao>(parameter);
                validation.Validate();
                ResourceAccess.MonitorAlocacao raMonitorAlocacao = new Sinacor.Servico.Bovespa.Alocacao.ResourceAccess.MonitorAlocacao();
                retorno = raMonitorAlocacao.ConsultarMensagensAlocacao(parameter);
                
               
                foreach (BusinessEntity.MensagemAlocacao item in retorno)
                {
                    item.Estado= AtualizarEstadoMensagemAlocacao(item);
                }
                
            }
            else
            {
                throw new BusinessException(109589);
            }

            return retorno;
        }

        /// <summary>
        /// Realiza o reenvio da mensagem informada como parâmetro de entrada
        /// </summary>
        /// <param name="parameter"></param>
        public BusinessEntity.ResultadoReenvio ReenviarMensagemAlocacao(BusinessEntity.DadosReenvioMensagemAlocacao parameter)
        {
            BusinessEntity.ResultadoReenvio reenvio = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.ResultadoReenvio();

            if (parameter != null)
            {
                this.ValidarPermissaoExecucao();
                Movimento.ResourceAccess.ControleMovimentoOrdens raMovimentoControleOrdens = new ControleMovimentoOrdens();
                Movimento.BusinessEntity.InformacoesMovimento beInformacoesMovimento = new InformacoesMovimento();

                DataMovimento datamovimento = new DataMovimento();

                beInformacoesMovimento = raMovimentoControleOrdens.ObterInformacoesMovimento(datamovimento);

                parameter.DataMovimento = beInformacoesMovimento.DataMovimento;

                ResourceAccess.MonitorAlocacao raMonitorAlocacao = new ResourceAccess.MonitorAlocacao();
                BusinessEntity.Resultado resultado = raMonitorAlocacao.ReenviarMensagemAlocacao(parameter);


                if (resultado.Sucesso == false)
                {
                    if (resultado.CodigoErro == -1)
                    {
                        throw new BusinessException(109642);
                    }
                    else
                    {
                        this.TratarExcecoes(resultado);
                    }

                }
                else
                {
                    //reenvio. = resultado.Valor;
                    return reenvio;
                }
            }
            else
            {
                throw new BusinessException(109641);
            }

            return reenvio;
        }

        /// <summary>
        /// Trata exceções geradas pelo Oracle
        /// </summary>
        /// <param name="resultado"></param>
        private void TratarExcecoes(BusinessEntity.Resultado resultado)
        {
            List<Object> listaParams;

            if (string.IsNullOrEmpty(resultado.Argumentos))
            {
                throw new BusinessException(resultado.CodigoErro);
            }
            else
            {
                listaParams = ErrorMessage.ConvertXmlArgumentsToParameters(resultado.Argumentos);
                throw new BusinessException(resultado.CodigoErro, listaParams.ToArray());
            } 

        }

        /// <summary>
        /// Realiza o tratamento de falhas de uma determinada mensagem
        /// </summary>
        /// <param name="parameter"></param>
        public bool TratarMensagemFalha(BusinessEntity.MensagemAlocacao parameter)
        {
            bool retorno;

            if (parameter != null)
            {
                this.ValidarPermissaoExecucao();

                if (parameter.Numero.HasValue)
                {
                    if (parameter.DataPregao.HasValue)
                    {
                        ResourceAccess.MonitorAlocacao raMonitorAlocacao = new ResourceAccess.MonitorAlocacao();
                        BusinessEntity.Resultado resultado = raMonitorAlocacao.TratarMensagemFalha(parameter);

                        
                        if (resultado.Sucesso == false)
                        {
                            retorno = Convert.ToBoolean(resultado.Valor);

                            if (resultado.CodigoErro == -1)
                            {
                                throw new BusinessException(109639);
                            }
                            else
                            {
                                this.TratarExcecoes(resultado);
                            }
                        }
                        else
                        {
                            retorno = Convert.ToBoolean(resultado.Valor);
                        }
                    }
                    else
                    {
                        throw new BusinessException(109638);
                    }
                }
                else
                {
                    throw new BusinessException(109637);
                }

            }
            else
            {
                throw new BusinessException(109634);
            }

            return retorno;
        }

        /// <summary>
        /// Realiza o tratamento de falhas de diversas mensagens passadas como parâmetro
        /// </summary>
        /// <param name="parameter"></param>
        public void TratarMensagensFalhas(List<BusinessEntity.MensagemAlocacao> parameter)
        {
            foreach (BusinessEntity.MensagemAlocacao entity in parameter)
            {
                this.TratarMensagemFalha(entity);
            }
        }

        /// <summary>
        /// Valida se o estado do movimento se encontra aberto
        /// </summary>
        private bool ValidarEstadoMovimento()
        {
            Movimento.ResourceAccess.ControleMovimentoOrdens raMovimentoControleOrdens = new ControleMovimentoOrdens();
            Movimento.BusinessEntity.InformacoesMovimento beInformacoesMovimento = new InformacoesMovimento();
            DataMovimento datamovimento = new DataMovimento();
            beInformacoesMovimento = raMovimentoControleOrdens.ObterInformacoesMovimento(datamovimento);

            if (beInformacoesMovimento.EstadoMovimento != Sinacor.Servico.Bovespa.Movimento.BusinessEntity.Enum.TipoMovimento.Aberto)
            {
                return false;
            }
            else
            {
                return true;
            }

        }

        /// <summary>
        /// Valida a permissão para execução de qualquer método da classe
        /// </summary>
        private void ValidarPermissaoExecucao()
        {
            bool retorno;
            if (AuthorizationContext.Current.CheckUserAccess("ORDM", "ORD"))
            {
                retorno = this.ValidarEstadoMovimento();
                if (retorno == false)
                {
                    throw new BusinessException(109628);
                }
            }
            else
            {
                throw new BusinessException(109627);
            }
        }
        #endregion
    }

}